/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2017.03.31                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_tbox_DatabaseBox_h
#define FreeMAPs_include_COMMON_tbox_DatabaseBox_h

#include "FreeMAPsConfig.h"

//COMMON headers
#include "COMMON/base/Common.h"

namespace FreeMAPs
{

/**
 * @brief POD data for class DatabaseBox
 *
 * The data in DatabaseBox need to reside in a POD class so that
 * HDF5's HOFFSET macro works.  (According to ANSI C++ standard,
 * it does not have to work with non-POD data.)
 */
struct DatabaseBox_POD {
    int d_dimension;
    int d_lo[FREEMAPS_DIM];
    int d_hi[FREEMAPS_DIM];
};

/**
 * Class DatabaseBox represents a box of up to MAX_DIM_VAL
 * dimensions in the AMR index space.  It is defined by lower and
 * upper bounds given by integer arrays.
 *
 * This box is an auxilliary data structure used by the database routines to
 * manipulate boxes.  This box type removes cyclic dependencies among the
 * database routines (which need a box) and the box (which needs the database
 * routines).  The box classes in the hierarchy package convert this box
 * structure into the standard SAMRAI box class used by the AMR algorithms.
 *
 * @internal This class should have @em NO data except for d_data.
 * See d_data for details.
 */

class DatabaseBox
{
public:
    /**
     * The default constructor creates a zero dimension empty box.
     */
    DatabaseBox();

    /**
     * Create a box of the specified dimension describing the index space
     * between lower and upper.
     */
    DatabaseBox(
        const int dim,
        const int * lower,
        const int * upper);

    /**
     * The copy constructor copies the index space of the argument box.
     */
    DatabaseBox(
        const DatabaseBox& box);

    /**
     * The assignment operator copies the index space of the argument box.
     */
    DatabaseBox&
    operator = (
        const DatabaseBox& box);

    /**
     * The destructor does nothing interesting.
     */
    ~DatabaseBox();

public:

    /**
     * Return whether the box is empty.  A box is empty if it has dimension
     * zero or if any part of the upper index is less than its corresponding
     * part of the lower index.
     */
    bool
    empty() const;

    /**
     * Return the dimension of this object.
     */
    inline int
    get_dim_val() const;

    inline void
    set_dim(
        const int dim);

    /**
     * Return the specified component (non-const) of the lower index of the box.
     *
     * @pre (i >= 0) && (i < getDimVal())
     */
    inline int&
    lower(
        const int i);

    /**
     * Return the specified component (non-const) of the upper index of the box.
     *
     * @pre (i >= 0) && (i < getDimVal())
     */
    inline int&
    upper(
        const int i);

    /**
     * Return the specified component (const) of the lower index of the box.
     *
     * @pre (i >= 0) && (i < getDimVal())
     */
    inline int
    lower(
        const int i) const;

    /**
     * Return the specified component (const) of the upper index of the box.
     *
     * @pre (i >= 0) && (i < getDimVal())
     */
    inline int
    upper(
        const int i) const;

    /**
     * Check whether two boxes represent the same portion of index space.
     */
    bool
    operator == (
        const DatabaseBox& box) const;

private:

    /*
     * @brief All data members in a POD type.
     *
     * Due to the need to compute offsets for data members and that
     * offsets cannot be computed for non-POD data, we place all
     * data members in a POD struct and own an object of that
     * struct.
     *
     * Data members are public so that the HDFDatabase need not
     * mirror this structure in defining a compound type for HDF.
     */
    DatabaseBox_POD d_data;
};

}

#include "COMMON/tbox/DatabaseBox.inl"

#endif
